package com.mylove.textprogressbar;

import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;

import com.mylove.textprogressbar.callback.IRefreshHead;

/**
 * @author myLove
 * @time 2017/12/29 17:04
 * @e-mail love@yanyi.red
 * @overview
 */

public class RefreshLayout extends FrameLayout {
    private static final String TAG = "RefreshLayout";
    private static final String HEAD_TAG = "head";
    private View mHeadView;
    private View mContentView;

    private IRefreshHead mIRefreshHead;

    private int mHeadViewHeight;

    private ValueAnimator mValueAnimator;

    /**
     * view需要移动的的距离
     */
    int moveDistance = 0;

    /**
     * 灵敏度，moveDistance * mTact = 实际 需要移动的距离
     */
    private float mHeadViewTact = 0.6f;

    /**
     * 当前的刷新布局状态
     */
    private int mStatus = STATUS_NONE;
    /**
     * 状态: 无
     */
    private static final int STATUS_NONE = 0;
    /**
     * 状态：刷新
     */
    private static final int STATUS_REFRESH = 1;

    /**
     * 方向
     */
    private int mDirection = DIRECTION_NONE;
    private static final int DIRECTION_NONE = 0;
    /**
     * 划动方向：向上划（加载更多动作）
     */
    private static final int DIRECTION_DOWN = 2;

    /**
     * 动画的执行时间,默认是200ms
     */
    int mAnimatorDuration = ANIMATOR_DEFAULT_DURATION;
    /**
     * 动画的默认执行时间
     */
    private static int ANIMATOR_DEFAULT_DURATION = 200;
    /**
     * 自动刷新的动画默认执行时间
     */
    private static int ANIMATOR_AUTO_REFRESH_DURATION = 500;

    /**
     * 是否拦截事件
     */
    boolean interception;
    /**
     * 是否为自动刷新
     */
    boolean isAutoRefresh = false;
    /**
     * 自动刷新动画监听器
     */
    private AutoRefreshAnimatorListener mAutoRefreshAnimatorListener = new AutoRefreshAnimatorListener();

    /**
     * 刷新布局的排放方式
     */
    private int mRefreshStyle;
    /**
     * 刷新头布局在刷新内容之下
     */
    private static final int STYLE_BELOW = 1;
    /**
     * 刷新头布局与刷新内容并排
     */
    private static final int STYLE_DEFAULT = 2;

    private boolean index = false;
    private Context mContext;
    private String SHANAME = "sha_name";
    private String INDEX = "index";
    private DefaultHeadView defaultHeadView;
    private DefaultHeadView2 defaultHeadView2;
    private float num1 = 100;
    private float num2 = 150;
    private float num3 = 400;
    private float size = 400;
    private int time = 2;


    public RefreshLayout(Context context) {
        this(context, null);
        mContext = context;
    }

    public RefreshLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
        mContext = context;
    }

    public RefreshLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        initAttrs(attrs);
        init();
    }

    /**
     * 只针对默认头部
     *
     * @param size
     * @return
     */
    public RefreshLayout setSize(float size) {
        this.size = size;
        if (index) {
            ((DefaultHeadView) mHeadView).setSize(size);
        }
        return this;
    }

    /**
     * 只针对默认头部
     *
     * @param time
     * @return
     */
    public RefreshLayout setTime(int time) {
        this.time = time;
        if (index) {
            ((DefaultHeadView) mHeadView).setTime(time);
        }
        return this;
    }

    /**
     * 只针对默认头部
     *
     * @param num1
     * @param num2
     * @param num3
     * @return
     */
    public RefreshLayout setNum(float num1, float num2, float num3) {
        this.num1 = num1;
        this.num2 = num2;
        this.num3 = num3;
        if (index) {
            ((DefaultHeadView) mHeadView).setNum(num1, num2, num3);
        }
        return this;
    }

    private void initAttrs(AttributeSet attrs) {
        TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.RefreshLayout);
        mRefreshStyle = ta.getInt(R.styleable.RefreshLayout_refresh_style, STYLE_DEFAULT);
        Log.d(TAG, "RefreshStyle: " + mRefreshStyle);
        ta.recycle();
    }

    private void init() {
        index = SharedUtil.getInstance(SHANAME, mContext).getShaBoolean(INDEX, index);
        defaultHeadView = new DefaultHeadView(getContext());
        defaultHeadView.setNum(num1, num2, num3)
                .setSize(size)
                .setTime(time);
        defaultHeadView2 = new DefaultHeadView2(getContext());
        if (index) {
            mHeadView = defaultHeadView;
        } else {
            mHeadView = defaultHeadView2;
        }
        mHeadView.setTag(HEAD_TAG);
        mIRefreshHead = (IRefreshHead) mHeadView;
        mHeadViewHeight = mIRefreshHead.headViewHeight();
    }

    public boolean isIndex() {
        return index;
    }

    public void setIndex(boolean index) {
        SharedUtil.getInstance(SHANAME, mContext).saveShaBoolean(INDEX, index);
        this.index = index;
        if (index) {
            mHeadView = defaultHeadView;
        } else {
            mHeadView = defaultHeadView2;
        }
        mIRefreshHead = (IRefreshHead) mHeadView;
        mHeadViewHeight = mIRefreshHead.headViewHeight();

        addHeadView(mHeadView);
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        if (getChildCount() > 1) {
            throw new IllegalArgumentException(">>>>---- do refresh direct view count must equal 1 ----<<<<");
        }
        mContentView = this.getChildAt(0);

        addHeadView(mHeadView);
    }

    /**
     * 添加刷新头
     *
     * @param headView 头布局
     */
    private void addHeadView(View headView) {
        this.removeView(findViewWithTag(HEAD_TAG));

        //重新添加头布局
        LayoutParams headParams = new LayoutParams(LayoutParams.MATCH_PARENT, mHeadViewHeight);
        if (mRefreshStyle == STYLE_BELOW) {
            this.addView(headView, 0, headParams);
            Log.d(TAG, "add headView below");
        } else {
            this.addView(headView, 1, headParams);
            Log.d(TAG, "add headView other > default or material");
        }
        headView.setTag(HEAD_TAG);
    }

    /**
     * 设置自定义的头布局
     *
     * @param headView 头布局
     */
    public void setHeadView(View headView) {
        if (!(headView instanceof IRefreshHead)) {
            throw new IllegalArgumentException("头布局headView必须实现 IRefreshHead 接口");
        }
        mHeadView = headView;
        mIRefreshHead = (IRefreshHead) headView;
        mHeadViewHeight = mIRefreshHead.headViewHeight();

        addHeadView(headView);

    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        b = getHeight();
        if (mRefreshStyle == STYLE_BELOW) {
            //below
            mHeadView.layout(0, 0, r, mHeadViewHeight);
            mContentView.layout(0, moveDistance, r, b + moveDistance);
        } else if (mRefreshStyle == STYLE_DEFAULT) {
            //default
            mHeadView.layout(0, -mHeadViewHeight + moveDistance, r, moveDistance);
            mContentView.layout(0, moveDistance, r, b + moveDistance);
        } else {
            //material
            mHeadView.layout(0, -mHeadViewHeight + moveDistance, r, moveDistance);
            if (mDirection == DIRECTION_DOWN) {
                mContentView.layout(0, 0, r, b);
            } else {
                mContentView.layout(0, moveDistance, r, b + moveDistance);
            }
        }

    }


    int downY;
    int downX;

    int diffY;
    int diffX;


    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        //如果此时是在刷新中或是在加载更多中就不要对事件进行自定义的拦截
        if (mStatus == STATUS_REFRESH) {
            return super.dispatchTouchEvent(ev);
        }
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downY = (int) ev.getY();
                downX = (int) ev.getX();
                mDirection = DIRECTION_NONE;
                interception = false;
//                Log.d(TAG, "dispatchTouchEvent down");
                break;
            case MotionEvent.ACTION_MOVE:
                diffY = (int) (downY - ev.getY());
                diffX = (int) (downX - ev.getX());
                if (Math.abs(diffX) > Math.abs(diffY)) {
                    return super.dispatchTouchEvent(ev);
                }
                if (diffY < 0) {
                    boolean contentViewCanScrollDown = ViewCompat.canScrollVertically(mContentView, -1);
                    if (!contentViewCanScrollDown) {
                        Log.d(TAG, "下拉 ");
                        mDirection = DIRECTION_DOWN;
                        if (!interception) {
                            mIRefreshHead.onStart();
                        }
                        interception = true;
                    }
                }
                break;
        }
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        //如果此时是在刷新中或是在加载更多中就不要对事件进行自定义的拦截
        if (mStatus == STATUS_REFRESH) {
            return super.onInterceptTouchEvent(ev);
        }

        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                Log.d(TAG, "onInterceptTouchEvent down:");
                break;
            case MotionEvent.ACTION_MOVE:
//                if (mDirection == DIRECTION_DOWN) {
//                    mIRefreshHead.onStart();
//                } else if (mDirection == DIRECTION_UP) {
//                    mILoadMoreFoot.onStart();
//                }
                Log.d(TAG, "onInterceptTouchEvent move:" + interception);
                return interception;
        }
        return super.onInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //如果此时是在刷新中或是在加载更多中就不要对事件进行自定义的拦截
        if (mStatus == STATUS_REFRESH) {
            return super.onTouchEvent(event);
        }
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                Log.d(TAG, "onTouchEvent down:");
                return true;
            case MotionEvent.ACTION_MOVE:
                move((int) event.getY());
                Log.d(TAG, "onTouchEvent move:" + interception);
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                int upY = (int) event.getY();
                if (mDirection == DIRECTION_DOWN) {
                    mIRefreshHead.onFingerUp(moveDistance);
                    if (moveDistance >= mHeadViewHeight) {
                        //触发刷新
                        reset((int) ((upY - downY) * mHeadViewTact), mHeadViewHeight);
                        mStatus = STATUS_REFRESH;
                        if (null != mOnRefreshListener) {
                            mOnRefreshListener.onRefresh();
                        }
                    } else {
                        //回弹
                        mStatus = STATUS_NONE;
                        reset((int) ((upY - downY) * mHeadViewTact), 0);
                    }
                }
                break;

        }
        return super.onTouchEvent(event);
    }

    /**
     * 移动布局
     *
     * @param moveY 手指移动的Y坐标
     */
    private void move(int moveY) {
        if (mDirection == DIRECTION_DOWN) {
            //下移
            moveDistance = (int) ((moveY - downY) * mHeadViewTact);
            mIRefreshHead.onPullDown(moveDistance);
        }
        Log.d(TAG, "moveDistance: " + moveDistance);

        requestLayout();
    }

    /**
     * 重置
     *
     * @param startY 起始Y
     * @param endY   结束Y
     */
    private void reset(int startY, int endY) {
        Log.d(TAG, "startY: " + startY + " endY: " + endY);
        mValueAnimator = ValueAnimator.ofInt(startY, endY);
        mValueAnimator.setDuration(mAnimatorDuration);
        mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int value = (int) animation.getAnimatedValue();
                Log.d(TAG, "value: " + value);
                moveDistance = value;
                requestLayout();
            }
        });
        mValueAnimator.addListener(mAutoRefreshAnimatorListener);
        mValueAnimator.start();

    }

    private class AutoRefreshAnimatorListener implements Animator.AnimatorListener {

        @Override
        public void onAnimationStart(Animator animation) {
            if (isAutoRefresh) {
                mIRefreshHead.onStart();
            }
        }

        @Override
        public void onAnimationEnd(Animator animation) {
            ValueAnimator valueAnimator = (ValueAnimator) animation;
            int value = (int) valueAnimator.getAnimatedValue();
            mIRefreshHead.onFingerUp(value);
            if (isAutoRefresh && null != mOnRefreshListener) {
                mOnAutoRefreshListener.onAutoRefresh();
            }
            isAutoRefresh = false;
            mAnimatorDuration = ANIMATOR_DEFAULT_DURATION;
        }

        @Override
        public void onAnimationCancel(Animator animation) {

        }

        @Override
        public void onAnimationRepeat(Animator animation) {

        }
    }


    /**
     * 设置刷新
     *
     * @param refresh true为刷新,false为关闭刷新
     */
    public void setRefresh(boolean refresh) {
        if (refresh) {
            mDirection = DIRECTION_DOWN;
            mStatus = STATUS_REFRESH;
            isAutoRefresh = true;
            mAnimatorDuration = ANIMATOR_AUTO_REFRESH_DURATION;
            reset(0, mHeadViewHeight);
        } else {
            if (mStatus == STATUS_NONE) {
                return;
            }
            if (mDirection == DIRECTION_DOWN) {
                reset(mHeadViewHeight, 0);
                mIRefreshHead.onStop();
            }
            mStatus = STATUS_NONE;
        }
        if (index) {
            defaultHeadView.setBoo(true).setNum(num1, num2, num3).setSize(size).setTime(time);
        }
    }

    /**
     * 当前是否在加载中或是刷新中
     *
     * @return
     */
    public boolean isRefresh() {
        return mStatus != STATUS_NONE;
    }


    OnRefreshListener mOnRefreshListener;
    OnAutoRefreshListener mOnAutoRefreshListener;

    /**
     * 设置手动下拉刷新回调接口
     *
     * @param onRefreshListener 刷新回调接口
     */
    public void setOnRefreshListener(OnRefreshListener onRefreshListener) {
        this.mOnRefreshListener = onRefreshListener;
    }

    /**
     * 设置自动下拉刷新回调接口
     */
    public void setOnAutoRefreshListener(OnAutoRefreshListener onAutoRefreshListener) {
        this.mOnAutoRefreshListener = onAutoRefreshListener;
    }

    /**
     * 手动下拉刷新回调接口
     */
    public interface OnRefreshListener {
        /**
         * 当刷新被触发时会调用此方法
         */
        void onRefresh();
    }

    /**
     * 自动下拉刷新回调接口
     */
    public interface OnAutoRefreshListener {
        /**
         * 当刷新被触发时会调用此方法
         */
        void onAutoRefresh();
    }
}
